home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Technical Documentation / Sample Code / DTS.Lib & Samples / DTS.Lib / Print.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-10-22  |  9.9 KB  |  369 lines  |  [TEXT/MPS ]

  1. /*
  2. ** Apple Macintosh Developer Technical Support
  3. **
  4. ** Program:     DTS.Lib
  5. ** File:        print.c
  6. ** Written by:  Eric Soldan
  7. ** Based on:    Code from Pete "Luke" Alexander.
  8. **
  9. ** Copyright © 1989-1991 Apple Computer, Inc.
  10. ** All rights reserved.
  11. */
  12.  
  13.  
  14.  
  15. /*****************************************************************************/
  16.  
  17.  
  18.  
  19. #include "DTS.Lib2.h"
  20. #include "DTS.Lib.Common.h"
  21. #include "DTS.Lib.protos.h"
  22.  
  23. #ifndef __ERRORS__
  24. #include <Errors.h>
  25. #endif
  26.  
  27. #ifndef __RESOURCES__
  28. #include <Resources.h>
  29. #endif
  30.  
  31. #ifndef __STRINGUTILS__
  32. #include "StringUtils.h"
  33. #endif
  34.  
  35.  
  36.  
  37. /*****************************************************************************/
  38.  
  39.  
  40.  
  41. static pascal void    PrintIdleProc(void);
  42. short                gPrintPage;
  43. static DialogPtr    gPrintingStatusDialog;
  44.  
  45.  
  46.  
  47. /*****************************************************************************/
  48.  
  49.  
  50.  
  51. /* This print-loop function is designed to be called under various situations.
  52. ** The big issue that it handles is finder printing.  If multiple documents
  53. ** are to be printed from the finder, the user should only see one job dialog
  54. ** for all the files.  (If a job dialog is shown for each file, how does the
  55. ** user know for which file the dialog is for?)  So, for situations where
  56. ** there is more than one file to be printed, call this code the first time
  57. ** with the firstJob boolean true.  Normally, the jobDlg boolean will also
  58. ** be true, except that under 7.0, you may be printing in the background.
  59. ** If this is the case, you don't want a job dialog for even the first file,
  60. ** and you should pass in false for the jobDlg boolean in this case.  For
  61. ** files 2-N, you should pass false for both booleans.  For regular application
  62. ** printing, you should pass true for both booleans, since the file is the
  63. ** first (only) file, and you are not in the background.
  64. **
  65. ** After calling this function to print a document, you need to call it
  66. ** again with a nil document handle.  The print record for the first (or only)
  67. ** document printed is preserved in a static variable.  This is so that the
  68. ** job dialog information can be passed on to documents 2-N in the print job.
  69. ** Calling this function with the document handle nil tells this function
  70. ** that you are done printing documents, and that the print record for the
  71. ** first job can be disposed of. */
  72.  
  73. #pragma segment Print
  74. OSErr    PrintDocument(FileRecHndl frHndl, Boolean jobDlg, Boolean firstJob)
  75. {
  76.     OSErr            err;
  77.     THPrint            prRecHndl;
  78.     TPPrPort        printPort;
  79.     GrafPtr            oldPort;
  80.     short            i, keepResFile, copies, fstPage, lstPage;
  81.     TPrStatus        status;
  82.     ControlHandle    proceedButton;
  83.     Rect             rct;
  84.     Handle            txtHndl;
  85.     Str255            txt, txt2;
  86.  
  87.     static THPrint    prMergeHndl;
  88.  
  89.     if (!frHndl) {
  90.         if (prMergeHndl) {
  91.             DisposeHandle((Handle)prMergeHndl);
  92.             prMergeHndl = nil;
  93.         }
  94.         return(noErr);
  95.     }
  96.  
  97.     gPrintingStatusDialog = nil;
  98.  
  99.     if (!(prRecHndl = (THPrint)NewHandle(sizeof(TPrint)))) return(memFullErr);
  100.         /* If we can't generate a print record handle, we are out of here. */
  101.  
  102.     BlockMove((Ptr)&((*frHndl)->d.doc.fhInfo.print), (Ptr)(*prRecHndl), sizeof(TPrint));
  103.         /* Get the document's print info into the print record handle. */
  104.  
  105.     GetPort(&oldPort);
  106.  
  107.     DoSetCursor(&qd.arrow);
  108.     PrOpen();
  109.     err = PrError();
  110.  
  111.     if (!err) {
  112.         keepResFile = CurResFile();
  113.  
  114.         if (!(*frHndl)->d.doc.fhInfo.printRecValid) {
  115.             PrintDefault(prRecHndl);            /* The document print record was never 
  116.             err = PrError();                    ** initialized.  Now is is. */
  117.         }            
  118.         if (!err) {
  119.             PrValidate(prRecHndl);        /* Do this just 'cause Apple says so. */
  120.             err = PrError();
  121.         }
  122.         if (!err) {
  123.             if (jobDlg) {                /* User gets to click some buttons. */
  124.                 UnhiliteWindows();
  125.                 if (!(PrJobDialog(prRecHndl)))
  126.                     err = userCanceledErr;
  127.                 else
  128.                     err = PrError();
  129.                 HiliteWindows();
  130.             }
  131.         }
  132.         if (!err) {
  133.             if (!firstJob) {
  134.                 fstPage = (*prMergeHndl)->prJob.iFstPage;
  135.                 lstPage = (*prMergeHndl)->prJob.iLstPage;
  136.                 PrJobMerge(prMergeHndl, prRecHndl);
  137.                 (*prMergeHndl)->prJob.iFstPage = (*prRecHndl)->prJob.iFstPage = fstPage;
  138.                 (*prMergeHndl)->prJob.iLstPage = (*prRecHndl)->prJob.iLstPage = lstPage;
  139.                 err = PrError();
  140.                     /* For documents other than the first, do the PrJobMerge thing.
  141.                     ** Unfortunately, PrJobMerge is kind of broken.  The first and last
  142.                     ** page fields have to be cached and put back.  The rest of PrJobMerge
  143.                     ** seems to work okay. */
  144.             }
  145.         }
  146.  
  147.         if (!err) {            /* Put the defaulted/validated/jobDlg'ed print record in the doc. */
  148.             fstPage = (*prRecHndl)->prJob.iFstPage;
  149.             lstPage = (*prRecHndl)->prJob.iLstPage;
  150.             copies  = (*prRecHndl)->prJob.iCopies;
  151.             BlockMove((Ptr)(*prRecHndl), (Ptr)&((*frHndl)->d.doc.fhInfo.print), sizeof(TPrint));
  152.             (*frHndl)->d.doc.fhInfo.printRecValid = true;
  153.  
  154.             gPrintingStatusDialog = nil;
  155.             i = ((*prRecHndl)->prStl.wDev >> 8) & 0xFF;
  156.             if ((i == 1) || (i == 2))
  157.                 gPrintingStatusDialog = GetNewDialog(rPrStatusDlg, nil, (WindowPtr)-1);
  158.             if (gPrintingStatusDialog) {
  159.                     /* The ImageWriter driver uses ParamText, so we can’t.
  160.                     ** If we try to, then the printer name shows up, instead of
  161.                     ** the document name.  Due to this, we have to parse our
  162.                     ** own text.  We expect dialog item#4 to have a c/r in it.
  163.                     ** We use the c/r instead of ^0, due to the ImageWriter driver.
  164.                     ** We just replace the c/r with the name of the document. */
  165.                 GetDItem(gPrintingStatusDialog, 4, &i, (Handle *)&txtHndl, &rct);
  166.                 GetIText(txtHndl, txt);
  167.                 for (i = *txt; i; --i) {
  168.                     if (txt[i] == 13) {
  169.                         txt[i] = *txt - i;
  170.                         txt[0] = i - 1;
  171.                         break;
  172.                     }
  173.                 }        /* We now have two pascal strings -- one right after the other. */
  174.                 pcpy(txt2, txt);                                /* Copy the first string. */
  175.                 pcat(txt2, (*frHndl)->fileState.fss.name);        /* Append the document name. */
  176.                 pcat(txt2, txt + *txt + 1);                        /* Append the second string. */
  177.                 SetIText(txtHndl, txt2);
  178.                 GetDItem(gPrintingStatusDialog, 1, &i, (Handle *)&proceedButton, &rct);
  179.                 HiliteControl(proceedButton, 255);
  180.                     /* Setup the proceed/pause/cancel dialog with the document name. */
  181.                 (*prRecHndl)->prJob.pIdleProc = PrintIdleProc;
  182.                 UseResFile(keepResFile);        /* Hook in the proceed/pause/cancel dialog. */
  183.                 UnhiliteWindows();
  184.             }
  185.  
  186.             for (i = 1; (i <= copies) && (!err); ++i) {
  187.  
  188.                 printPort = PrOpenDoc(prRecHndl, nil, nil);
  189.                 if (!(err = PrError())) {
  190.  
  191.                     gPrintPage = 1;
  192.                     while (gPrintPage <= lstPage) {
  193.  
  194.                         PrOpenPage(printPort, nil);
  195.  
  196.                         if (!(err = PrError()))
  197.                             err = DoImageDocument(frHndl);
  198.                                 /* Do the print thing here. */
  199.  
  200.                         PrClosePage(printPort);
  201.  
  202.                         if (!gPrintPage) break;
  203.                         ++gPrintPage;
  204.                     }
  205.                     gPrintPage = 0;
  206.                     PrCloseDoc(printPort);
  207.                 }
  208.             }
  209.         }
  210.  
  211.         if (
  212.             (!err) &&
  213.             ((*prRecHndl)->prJob.bJDocLoop == bSpoolLoop) &&
  214.             (!(err = PrError()))
  215.         ) {
  216.             PrPicFile(prRecHndl, nil, nil, nil, &status);
  217.             err = PrError();
  218.         }
  219.     }
  220.  
  221.     if (firstJob)
  222.         prMergeHndl = prRecHndl;
  223.     else
  224.         DisposeHandle((Handle)prRecHndl);
  225.  
  226.     if (gPrintingStatusDialog)
  227.         DisposeDialog(gPrintingStatusDialog);
  228.  
  229.     PrClose();
  230.     SetPort(oldPort);
  231.     HiliteWindows();
  232.  
  233.     if (err == iIOAbortErr)
  234.         err = noErr;
  235.  
  236.     return(err);
  237. }
  238.  
  239.  
  240.  
  241. /*****************************************************************************/
  242.  
  243.  
  244.  
  245. /* DonePrinting makes sure that PrintDocument gets rid of the prMergeHndl
  246. ** print record that is used for multiple document printing.  Call this after
  247. ** or the last document is printed, or you get a memory leak. */
  248.  
  249. #pragma segment Print
  250. void    DonePrinting(void)
  251. {
  252.     PrintDocument(nil, false, false);
  253. }
  254.  
  255.  
  256.  
  257. /*****************************************************************************/
  258.  
  259.  
  260.  
  261. /* PrintIdleProc will handle events in the 'Printing Status Dialog' which
  262. ** gives the user the option to 'Proceed', 'Pause', or 'Cancel' the current
  263. ** printing job during print time.
  264. **
  265. ** The buttons:
  266. **        1: Proceed
  267. **        2: Pause
  268. **        3: Cancel
  269. */
  270.  
  271. #pragma segment Print
  272. pascal void    PrintIdleProc(void)
  273. {
  274.     Boolean                button, paused;
  275.     ControlHandle        pauseButton, proceedButton;
  276.     DialogPtr            aDialog;
  277.     EventRecord            anEvent;
  278.     GrafPtr                oldPort;
  279.     Rect                 rct;
  280.     short                item, itemType, keepResFile;
  281.  
  282.     GetPort(&oldPort);
  283.  
  284.     UseResFile(keepResFile = CurResFile());
  285.  
  286.     GetDItem(gPrintingStatusDialog, 1, &itemType, (Handle *)&proceedButton, &rct);
  287.     HiliteControl(proceedButton, 255);
  288.     GetDItem(gPrintingStatusDialog, 2, &itemType, (Handle *)&pauseButton, &rct);
  289.  
  290.     paused = false;
  291.     do {
  292.         if (GetNextEvent((mDownMask + mUpMask + updateMask), &anEvent)) {
  293.             if (gPrintingStatusDialog != FrontWindow())
  294.                 SelectWindow(gPrintingStatusDialog);
  295.  
  296.             if (IsDialogEvent(&anEvent)) {
  297.                 button = DialogSelect(&anEvent, &aDialog, &item);
  298.  
  299.                 if ((button) && (aDialog == gPrintingStatusDialog)) {
  300.                     switch (item) {
  301.                         case 1:
  302.                             HiliteControl(pauseButton, 0);        /* Enable PAUSE    */
  303.                             HiliteControl(proceedButton, 255);    /* Disable PROCEED */
  304.                             paused = false;
  305.                             break;
  306.                         case 2:
  307.                             HiliteControl(pauseButton, 255);    /* Disable PAUSE  */
  308.                             HiliteControl(proceedButton, 0);    /* Enable PROCEED */
  309.                             paused = true;
  310.                             break;
  311.                         case 3:
  312.                             PrSetError(iPrAbort);               /* CANCEL printing */
  313.                             paused = false;
  314.                             break;
  315.                     }
  316.                 }
  317.             }
  318.         }
  319.     } while (paused != false); 
  320.  
  321.     SetPort(oldPort);
  322. }
  323.  
  324.  
  325.  
  326. /*****************************************************************************/
  327.  
  328.  
  329.  
  330. #pragma segment Print
  331. OSErr    PresentStyleDialog(FileRecHndl frHndl)
  332. {
  333.     OSErr        err;
  334.     THPrint        prRecHndl;
  335.  
  336.     if (!(prRecHndl = (THPrint)NewHandle(sizeof(TPrint)))) return(memFullErr);
  337.  
  338.     PrOpen();
  339.  
  340.     if (!(err = PrError())) {
  341.  
  342.         BlockMove((Ptr)&(*frHndl)->d.doc.fhInfo.print, (Ptr)*prRecHndl, sizeof(TPrint));
  343.             /* Get data, valid or not. */
  344.  
  345.         if (!(*frHndl)->d.doc.fhInfo.printRecValid)
  346.             PrintDefault(prRecHndl);
  347.         else
  348.             PrValidate(prRecHndl);
  349.  
  350.         if (!(err = PrError())) {
  351.             UnhiliteWindows();
  352.             if (PrStlDialog(prRecHndl)) {
  353.                 BlockMove((Ptr)*prRecHndl, (Ptr)&(*frHndl)->d.doc.fhInfo.print, sizeof(TPrint));
  354.                 (*frHndl)->d.doc.fhInfo.printRecValid = true;
  355.             }
  356.             else err = userCanceledErr;
  357.             HiliteWindows();
  358.         }
  359.     }
  360.  
  361.     DisposeHandle((Handle)prRecHndl);
  362.     PrClose();
  363.  
  364.     return(err);
  365. }
  366.  
  367.  
  368.  
  369.